import os,glob,uuid,io,cv2,qrcode, random
from multiprocessing import  Queue, Value, Lock
import ctypes,os,re,time,json,requests,base64,pytesseract,matplotlib
from sqlalchemy import extract
matplotlib.use('Agg')  
from datetime import datetime, timedelta
from threading import Thread
from PIL import Image
from werkzeug.utils import secure_filename
from io import BytesIO
import numpy as np
import threading
import matplotlib.pyplot as plt
from sqlalchemy import text
from flask import Flask, render_template,send_from_directory, send_file
from flask_socketio import SocketIO, emit, join_room, leave_room

from flask import Flask, request, jsonify,current_app, render_template
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

app = Flask(__name__)
CORS(app) #跨域使用

# app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:root@localhost/userdata'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@localhost/userdata_backup'

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

#学生账号表
class Student(db.Model):
    id = db.Column(db.Integer, primary_key=True) #ID主键，学号
    username = db.Column(db.String(80), unique=True, nullable=False) #名字不能为空，唯一键  
    classname = db.Column(db.String(80), nullable=False)#行政班级班级名不能为空    
    telephone  = db.Column(db.String(20), unique=True) #电话可以为空，唯一键
    password  = db.Column(db.String(20),  nullable=False)#密码不能为空
    sex = db.Column(db.Boolean,  nullable=False) #性别，true是男false是女
  
#教师账号表
class Teacher(db.Model):
    id = db.Column(db.Integer, primary_key=True) #ID主键，工号
    username = db.Column(db.String(80), unique=True, nullable=False) #名字不能为空，唯一键  
    telephone  = db.Column(db.String(20), unique=True) #电话可以为空，唯一键
    password  = db.Column(db.String(20),  nullable=False)#密码不能为空
    
#用户头像
class UserAvatar(db.Model):
    id = db.Column(db.Integer, primary_key=True) #ID主键，用户号
    path = db.Column(db.String(80), unique=True, nullable=False,default='default.png') #路径不能为空，唯一键 
    
#课程头像    
class courseAvatar(db.Model):
    id = db.Column(db.Integer, primary_key=True) #ID主键，用户号
    path = db.Column(db.String(80), unique=True, nullable=False,default='default.png')
    
#班级   
class classRoom(db.Model):
    id = db.Column(db.Integer,autoincrement=True, primary_key=True) #ID主键，班级号
    classname = db.Column(db.String(80), nullable=False) #班级(课程名称)   

#群聊历史记录
class groupHistory(db.Model):
    id = db.Column(db.Integer,autoincrement=True, primary_key=True) 
    groupid=db.Column(db.Integer,nullable=False)
    userid=db.Column(db.Integer,nullable=False)  
    time = db.Column(db.DateTime,nullable=False)
    info = db.Column(db.String(120),nullable =False)
    
#群聊列表
class groupList(db.Model):
    id = db.Column(db.Integer,autoincrement=True, primary_key=True) 
    groupid=db.Column(db.Integer, nullable=False) #-1代表群聊创建者
    groupname = db.Column(db.String(80), nullable=False)
    group_userid=db.Column(db.Integer, nullable=False) #群聊显示者
    
#班级的学生列表
class classUser(db.Model):
    id = db.Column(db.Integer,autoincrement=True, primary_key=True) #ID主键，我也不知道拿去干嘛
    courseid = db.Column(db.Integer, nullable=False) #课程id
    userid =db.Column(db.Integer,nullable=False) #学生id
    grade = db.Column(db.Integer, nullable=False) #成绩
    
#课程的班级列表
class classList(db.Model):
    id = db.Column(db.Integer,autoincrement=True, primary_key=True) #ID主键，我也不知道拿去干嘛
    courseid = db.Column(db.Integer, nullable=False) #课程id
    classid =db.Column(db.Integer,nullable=False) 
    classnum=db.Column(db.Integer,nullable=False) 
    
#教的课程
class teachCourse(db.Model):
    select_id = db.Column(db.Integer, nullable=False ,primary_key=True,autoincrement=True)#课程id主键
    class_id=db.Column(db.Integer,nullable=False) #课程的id
    id=db.Column(db.Integer,nullable=False) #用户的id
    course_name = db.Column(db.String(80), nullable=False) #课程名称
    status = db.Column(db.Boolean,  nullable=False) #完课状态 true是没有完课，false是完课
    teacher_name = db.Column(db.String(80), nullable=False) #课程名称
    is_teacher = db.Column(db.Boolean,  nullable=False) #true是老师，false是学生

#课程签到数据
class checkIn(db.Model):
    id = db.Column(db.Integer, nullable=False ,primary_key=True,autoincrement=True)#id主键
    courseid=db.Column(db.Integer,nullable=False) #课程id
    userid=db.Column(db.Integer,nullable=False) #学生id
    status=db.Column(db.Boolean,  nullable=False)#签到状态
    reason=db.Column(db.Integer) #请假原因 0.迟到 1.缺勤 2.病假 3.事假
    time = db.Column(db.DateTime,nullable=False)
    
username={}
classid={}
with app.app_context():
    db.create_all()
    class_datas = classRoom.query.all()
    #构建classname-classid的哈希表
    for class_data in class_datas:
        classid[class_data.classname] =class_data.id
    
    students = Student.query.all()
    teachers = Teacher.query.all()
    #构建学生和老师的id-name哈希表
    for student in students:
        username[student.id] = student.username
        
    for teacher in teachers:
        username[teacher.id] = teacher.username
    
migrate = Migrate(app, db)


#工具
    #返回体构建
        #成功请求(填入返回的数据)
def response_success(data):
    response = [{'code':200},{'status':'ok'},{'data':data}]
    return jsonify(response)
        #错误请求(填入错误码，错误信息)
def response_error(code,status):
    response = [{'code':code},{'status':status},{'data':None}]
    return jsonify(response)

    #获取请求体
def get_request(request,body):
    if request == None:
        return None
    
    if request.is_json:
        data = request.get_json()
        return data.get(body)
    else:
        return request.form.get(body)

    #构建学生信息的字典
def build_student_data(id,username,classname,telephone,sex,password='保密'):
    return {
        'id': id,
    'username': username,
    'classname': classname,
    'telephone': telephone,
    'password':password,
    'sex':sex
    }
def build_teacher_data(id,username,telephone,password='保密'):
    return {
        'id': id,
    'username': username,  
    'telephone': telephone,
    'password':password
    }
    #使用原生mysql指令
def mysql(command:str,data):
    
    sql = text(command)
    try:
        data =db.session.execute(sql,data)
        if data:
            return data.fetchone()
        else:
            return None
    except Exception as e:
        print(e)
        return None
    
    # 检查文件扩展名是否允许
def allowed_file(filename):
    return '.' in filename and \
         filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

    # 生成二维码
@app.route('/debug/class/generate-qrcode/<front>', methods=['GET','POST'])
def generate_class_qrcode(front):       
    code=random.randint(1, 100);
    qrcode_content = f"{front}{code}"
    
    # 生成二维码
    img = qrcode.make(qrcode_content)
    
    # 将二维码保存到内存
    img_io = io.BytesIO()
    img.save(img_io, 'PNG')
    img_io.seek(0)
    
    return send_file(img_io, mimetype='image/png')

    #上传图片
def update_avatar(request,PATH):
    #检查一下是否上传了图片
    if 'file' not in request.files:
        return response_error( 500,'没有文件，错误的请求')
    
    file = request.files['file']
    # 如果用户没有选择文件
    if file.filename == '':
        return response_error( 502,'请上传文件')
    
    if file and allowed_file(file.filename):
                     
        name, extension = os.path.splitext(file.filename)
        id = get_request(request,'id')
        name =str(id)
        file_path = name +extension #构建图片文件名（用学号+后缀构建）
        
        pattern = os.path.join(PATH, name + '.*')# 构建匹配模式：name + 任意扩展名
     
        matching_files = glob.glob(pattern) # 查找所有匹配的文件
 
        for file_path2 in matching_files:# 删除所有匹配的文件
            if os.path.exists(file_path2):
                os.remove(file_path2)
         
        file.save(PATH +file_path)
        
        
        return file_path,id
    else:
        return '',0
    
    #获取最后一条记录
def get_last_history(groupid):
    last_record = groupHistory.query.filter_by(groupid=groupid)\
                                .order_by(groupHistory.id.desc())\
                                .first()
    if last_record is None:
        return '还没有人发送消息喔'
    
    return f'[{username[last_record.userid]}]{last_record.info}'
def get_history(group_id):   
    #id=get_request(request,'user_id')
    
    #获取群聊的所有信息
    datas = groupHistory.query.filter_by(groupid = group_id).all() 

    result = []
    for data in datas:
        result.append({'userid':data.userid,'username':username[data.userid],'datatime':data.time.strftime("%Y-%m-%d %H:%M"),'info':data.info})
      
    return result
    
#测试连接的api
@app.route('/', methods=['POST', 'GET'])
def HelloWord():
    data = get_request(request,'test')
    return response_success(data)

#tcpSocket
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, cors_allowed_origins="*")

    # 存储连接的客户端
students_tcp = set()
teachers_tcp = set()
listen_tcp=set()

is_allow_send = False
allow_send_lock = threading.Lock() #保护权限变量
student_connect_lock = threading.Lock() #保护学生连接
teacher_connect_lock = threading.Lock() #保护教师连接
listen_connect_lock = threading.Lock() #保护监听连接


    # 学生连接
@socketio.on('student_connect')
def handle_student_connect():
    with student_connect_lock:
        students_tcp.add(request.sid)
        emit('connection_ack', {'message': '已连接到服务器'})    
        print(f"学生 {request.sid} 已连接，当前学生数: {len(students_tcp)}")
    
    # 教师连接
@socketio.on('teacher_connect')
def handle_teacher_connect():
    with teacher_connect_lock :
        teachers_tcp.add(request.sid)
        print(f"教师 {request.sid} 已连接")
        emit('connection_ack', {'message': '教师已连接到服务器'})
        
    # 监听连接
@socketio.on('listen_connect')
def handle_listen_connect():
    with listen_connect_lock:
        listen_tcp.add(request.sid)
        emit('connection_ack', {'message': '教师已连接到服务器'})
        print(f" {request.sid} 已连接，当前监听数: {len(listen_tcp)}")

@socketio.on('change_permission')
def change_permission(data):
    with allow_send_lock:
        permission = data.get('messge','')
        print(permission)
    if permission == 'teacher':    
        global is_allow_send
        with allow_send_lock:
            is_allow_send = not is_allow_send
            print(f"当前状态:{is_allow_send}")
        
    # 处理发送的广播消息
@socketio.on('broadcast_message')
def handle_broadcast_message(data):
        # 验证发送者是否拥有权限发送
    flag = False    
    with allow_send_lock:
        flag = is_allow_send
    if request.sid in teachers_tcp or flag == True:
        message = data.get('message', '')
        if message:
            with listen_connect_lock:
                send_group = listen_tcp
            # 向所有连接广播消息
            emit('receive_broadcast', {
                'message': message,
                'from': 'teacher'
            }, room=list(send_group))
            print(f"已发送给{len(send_group)}个用户")
            print(f"广播消息: {message}")
    else:
        emit('error', {'message': '没有发送权限，请联系教师获取'})
        print('权限不足的发送')
        
    # 断开连接处理
@socketio.on('disconnect')
def handle_disconnect():
    if request.sid in students_tcp:
        students_tcp.remove(request.sid)
        print(f"学生 {request.sid} 已断开，当前学生数: {len(students_tcp)}")
    if request.sid in teachers_tcp:
        teachers_tcp.remove(request.sid)
        print(f"教师 {request.sid} 已断开")
    if request.sid in listen_tcp:
        listen_tcp.remove(request.sid)
        print(f"监听{request.sid}已断开，当前监听数:{len(listen_tcp)}")

#直播管理
# 直播房间管理：room_id -> {host_sid, viewers}
live_rooms = {}
# 线程安全锁
live_room_lock = threading.Lock()

#向所有人广播消息
def broadcast_system_message(message):
    # 构造系统消息格式
    system_message = {
        'type': 'system',
        'content': message,
        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    }
    
    # 向所有教师广播
    for teacher_sid in teachers_tcp:
        emit('system_message', system_message, room=teacher_sid)
    
    # 向所有学生广播
    for student_sid in students_tcp:
        emit('system_message', system_message, room=student_sid)
        
#教师创建直播房间
@socketio.on('create_live_room')
def handle_create_live_room(data):
    print("收到请求")
    # 1. 验证请求者是否是教师（SID 在 teachers_tcp 中）
    if request.sid not in teachers_tcp:
        emit('live_error', {'message': '仅教师可创建直播'})
        return
    # 2. 生成唯一房间号
    room_id = f"live_{uuid.uuid4().hex[:6]}"
    print(room_id)
    print("房间号生成成功")
    # 3. 存储房间信息
    with live_room_lock:
        live_rooms[room_id] = {'host_sid': request.sid, 'viewers': set()}
    # 4. 向客户端返回房间号（通过 "live_room_created" 事件）
    emit('live_room_created', {'room_id': room_id, 'message': '直播房间创建成功'})
    print("房间号返回成功")

#学生加入直播房间
@socketio.on('join_live_room')
def handle_join_live_room(data):
    room_id = data.get('room_id')
    print(room_id)
    if not room_id or room_id not in live_rooms:
        emit('live_error', {'message': '直播房间不存在'})
        return
    
    # 验证是否为学生
    if request.sid not in students_tcp:
        emit('live_error', {'message': '仅学生可观看直播'})
        return
    
    with live_room_lock:
        live_rooms[room_id]['viewers'].add(request.sid)
        # 加入房间分组（便于后续广播）
        join_room(room_id)
    
    # 通知主播有新观众
    emit('live_viewer_joined', {
        'count': len(live_rooms[room_id]['viewers'])
    }, room=live_rooms[room_id]['host_sid'])
    
    # 通知学生加入成功
    emit('live_room_joined', {'message': '已加入直播'})

debug_time=0;
#处理直播流数据（教师发送，转发给所有学生）
@socketio.on('live_stream_data')
def handle_live_stream(data):
    room_id = data.get('room_id')
    raw_frame = data.get('frame_data')
    
    # 1. 基础验证
    if not raw_frame:
        emit('live_error', {'message': '未收到原始帧数据'})
        return

    # 2. 房间权限验证
    with live_room_lock:
        if not room_id or room_id not in live_rooms:
            emit('live_error', {'message': '无效的直播房间'})
            return
        if live_rooms[room_id]['host_sid'] != request.sid:
            emit('live_error', {'message': '没有推流权限'})
            return

    # 3. 处理帧数据
    try:
        frame_info = f"原始帧类型: {type(raw_frame)}"
        decoded_bytes = None

        # 处理字符串（Base64解码）
        if isinstance(raw_frame, str):
            frame_info += f", 字符串长度: {len(raw_frame)}"
            try:
                decoded_bytes = base64.b64decode(raw_frame)
                frame_info += "，已转换为字节流（Base64解码）"
            except Exception as e:
                raise ValueError(f"Base64解码失败：{str(e)}")
        elif isinstance(raw_frame, bytes):
            decoded_bytes = raw_frame
            frame_info += f", 字节长度: {len(decoded_bytes)}"
        else:
            raise TypeError(f"不支持的帧类型：{type(raw_frame)}")

        # 验证图像格式（通过文件头判断）
        if len(decoded_bytes) < 4:
            raise ValueError("解码后字节流过短，无法识别图像格式")
        
        # 常见图像文件头标识（魔法数）
        file_header = decoded_bytes[:4].hex().upper()  # 取前4字节转为16进制
        valid_formats = {
            'FFD8FF': 'JPEG',  # JPEG开头（前3字节）
            '89504E47': 'PNG',  # PNG开头（前4字节）
            '47494638': 'GIF',  # GIF开头
            '424D': 'BMP'  # BMP开头（前2字节）
        }
        frame_info += f", 文件头: 0x{file_header}"
        
        # 检查是否为支持的格式
        is_valid = False
        for magic, fmt in valid_formats.items():
            if file_header.startswith(magic):
                is_valid = True
                frame_info += f", 识别为{fmt}格式"
                break
        if not is_valid:
            raise ValueError(f"不支持的图像格式，文件头: 0x{file_header}")

        # 尝试打开图像
        img = Image.open(io.BytesIO(decoded_bytes))

        # 编码为JPEG（转发给学生端）
        jpeg_buffer = io.BytesIO()
        img.save(jpeg_buffer, format='JPEG', quality=80)
        jpeg_data = jpeg_buffer.getvalue()

        if len(jpeg_data) == 0:
            raise ValueError("JPEG二次编码失败")

        frame_data = base64.b64encode(jpeg_data).decode('utf-8').replace('\n', '')

    except Exception as e:
        error_msg = f"帧处理失败：{type(e).__name__} - {str(e)} | {frame_info}"
        print(f"编码错误: {error_msg}")
        emit('live_error', {'message': error_msg})
        return

    #print("准备转发消息")
    # 4. 转发数据
    emit('live_stream_data', {
        'room_id': room_id,
        'frame_data': frame_data,
        'timestamp': datetime.now().timestamp()
    }, room=room_id, include_self=False)
    
    

# 4. 离开直播房间
@socketio.on('leave_live_room')
def handle_leave_live_room(data):
    room_id = data.get('room_id')
    if not room_id or room_id not in live_rooms:
        return
    
    with live_room_lock:
        # 主播离开则关闭房间
        if live_rooms[room_id]['host_sid'] == request.sid:
            # 通知所有观众房间关闭
            emit('live_room_closed', {'message': '主播已结束直播'}, room=room_id)
            del live_rooms[room_id]
        # 观众离开
        elif request.sid in live_rooms[room_id]['viewers']:
            live_rooms[room_id]['viewers'].remove(request.sid)
            leave_room(room_id)
            # 通知主播观众数量变化
            emit('live_viewer_left', {
                'count': len(live_rooms[room_id]['viewers'])
            }, room=live_rooms[room_id]['host_sid'])

# 图片上传
    #配置
# UPLOAD_FOLDER = 'F:/TNOT/image/userAvatar/' #用户头像
# COURSE_AVATAR = 'F:/TNOT/image/classAvatar/' #课程头像

UPLOAD_FOLDER = 'D:/multimedia/image/userAvatar' #用户头像
COURSE_AVATAR = 'D:/multimedia/image/classAvatar' #课程头像

ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}# 目前只允许上传的图片格式
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['COURSE_AVATAR'] = COURSE_AVATAR

if not os.path.exists(UPLOAD_FOLDER): #确保路径存在
    os.makedirs(UPLOAD_FOLDER)
    
    #http用户头像上传
@app.route('/api/update_user_avatar', methods=['POST'])
def update_user_avatar():
    file_path,id = update_avatar(request,UPLOAD_FOLDER)
    if file_path != '':
        sql =text("insert into user_avatar(id,path) value(:id,:path) ON DUPLICATE KEY UPDATE path =:path")  
        db.session.execute(sql,{'id':id,'path':file_path})
        db.session.commit()
        return response_success('ok')
    else:
        response_error(502,f'请上传：{", ".join(ALLOWED_EXTENSIONS)}格式文件')


    #http上传课程头像        
@app.route('/api/update_course_avatar', methods=['POST'])
def update_course_avatar():
    file_path,id = update_avatar(request,COURSE_AVATAR)
    if file_path != '':
        sql =text("insert into course_avatar(id,path) value(:id,:path) ON DUPLICATE KEY UPDATE path =:path")  
        db.session.execute(sql,{'id':id,'path':file_path})
        db.session.commit()
        return response_success('ok')
    else:
        response_error(502,f'请上传：{", ".join(ALLOWED_EXTENSIONS)}格式文件')        
        
    #获取用户头像图片 
@app.route('/api/get_user_avatar/<user_id>', methods=['GET','POST'])
def get_user_image(user_id):
    data = mysql("select * from user_avatar where id =:user_id",{'user_id':user_id})
    
    if data is None:
        default_path = os.path.join(app.config['UPLOAD_FOLDER'], "default.png")
        if not os.path.exists(default_path):
            return response_error(502,"找不文件")
        path = default_path
    else:
        path = data.path
        
    filename = os.path.basename(path)
    
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename)

    #获取课程头像图片 
@app.route('/api/get_course_avatar/<course_id>', methods=['GET','POST'])
def get_course_image(course_id):
    data = mysql("select * from course_avatar where id =:course_id",{'course_id':course_id})
    
    if data is None:
        default_path = os.path.join(app.config['COURSE_AVATAR'], "default.png")
        if not os.path.exists(default_path):
            return response_error(502,"找不文件")
        path = default_path
    else:
        path = data.path
    
    filename = os.path.basename(path)
    
    return send_from_directory(app.config['COURSE_AVATAR'], filename)

#http课程管理
   #添加课程
@app.route('/api/add_course', methods=['GET','POST'])
def add_course():
    teacher_id=get_request(request,'teacher_id')
    course_name=get_request(request,'course_name')
    
    if teacher_id is None:
        return response_error(504,'教师字段未发送')
    
    if course_name is None:
        return response_error(504,'课程名未发送')
    
    else:
        teacher=Teacher.query.get(teacher_id)
        if teacher is None:
            return response_error(504,'id不存在不存在')
    course = teachCourse(id=teacher_id,status=True,course_name=course_name
                        ,teacher_name=teacher.username,is_teacher=True,class_id=-1)
    db.session.add(course)
    db.session.commit()
    
    return response_success('ok')


    #获取课程的学生
@app.route('/api/get_course_students', methods=['GET','POST'])
def get_course_students():

    course_id=get_request(request,'course_id')
    student_datas=classUser.query.filter_by(courseid=course_id).all()
    
    student_list=[]
    for student_data in student_datas:
        student_info = Student.query.get(student_data.userid)
        id=str(student_info.id)
        student_list.append({'id':id.zfill(10),'username':student_info.username,
                             'sex':int(student_info.sex),'grade':student_data.grade,
                             'classname':student_info.classname,
                             'telephone':student_info.telephone})
    return response_success(student_list)

    #添加学习的课程
@app.route('/api/add_study_course', methods=['GET','POST'])
def add_study_course():
    student_id=get_request(request,'student_id')
    course_id=get_request(request,'course_id')
    course_data=teachCourse.query.filter_by(select_id=course_id,is_teacher=True).first()
    if course_data == None:
        return response_error(504,'课程不存在')
    
    if len(teachCourse.query.filter_by(id=student_id,is_teacher=False,class_id=course_id).all())>=1:
        return response_error(504,'已经加过啦')
    
    course = teachCourse(id=student_id,status=True,course_name=course_data.course_name,
                         teacher_name=course_data.teacher_name,is_teacher=False,class_id=course_data.select_id)
    db.session.add(course)
    db.session.commit()
    return response_success('ok')

    #添加班级到课程
#@app.route('/api/add_class_to_course', methods=['GET','POST'])
def add_class_to_course(class_id,course_id):
    # class_id=get_request(request,'class_id')
    # course_id=get_request(request,'course_id')
    class_data=classList.query.filter_by(courseid=course_id,classid=class_id).all()
    if len(class_data) ==0:
        data = classList(courseid=course_id,classid=class_id,classnum=1)
        db.session.add(data)
        db.session.commit()
    else:
        class_data[0].classnum+=1;
        db.session.commit()
    #return response_success('ok')

    #添加学生到课程
@app.route('/api/add_course_students', methods=['GET','POST'])   
def add_course_students():
    student_id =get_request(request,'student_id')
    course_id=get_request(request,'course_id')
    student_data=Student.query.get(student_id)
    if  student_data is None:
        return response_error(504,'该用户不存在喔')
    
    if len(teachCourse.query.filter_by(select_id=course_id,is_teacher=True).all())==0:
        return response_error('该课程不存在喔')    
    user=classUser(courseid=course_id,userid=student_id,grade=0)
     
    if len(classUser.query.filter_by(courseid=course_id,userid=student_id).all()) >=1:
        return response_error(504,'用户已经在课程里咯')
    
    add_class_to_course(classid[student_data.classname],course_id)
    db.session.add(user)
    db.session.commit()
    return response_success('ok')

    #获取我教的课程以及学的课程
@app.route('/api/get_course', methods=['GET','POST'])    
def get_teach_course():
    id=get_request(request,'id')
    teacher_data=[]
    student_data=[]
    
    course_datas=teachCourse.query.filter_by(id=id).all()
    for course_data in course_datas:
        class_list=[]
        class_datas=classList.query.filter_by(courseid=course_data.select_id).all()
        for class_data in class_datas:
            classname=classRoom.query.get(class_data.classid).classname
            class_list.append({'classname':classname,'classnum':class_data.classnum})
        if course_data.is_teacher == True:    
            teacher_data.append({'class_list':class_list,'course_name':course_data.course_name,'teacher_name':course_data.teacher_name
                     ,'course_id':int(course_data.select_id)})
        else:
            student_data.append({'course_name':course_data.course_name,'teacher_name':course_data.teacher_name
                     ,'course_id':int(course_data.class_id)})
    
    return response_success([teacher_data,student_data])
           
#http用户管理

    #通过学号或手机号获取教师信息
@app.route('/api/get_teacher_data/<id>', methods=['GET','post'])
def get_teacher_data(id):
    user = mysql('select * from teacher where id = :id',{'id':id})
    if not user:   
        user = mysql('select * from teacher where telephone = :telephone',{'telephone':id})
    if user:    
        student_data=build_teacher_data(user.id,user.username,user.telephone)
        return response_success(student_data)
    else:
        return response_error(502,"账号获取异常")

    #通过学号或手机号获取学生信息
@app.route('/api/get_student_data/<id>', methods=['GET','post'])
def get_student_data(id):
    user = mysql('select * from student where id = :id',{'id':id})
    if not user:   
        user = mysql('select * from student where telephone = :telephone',{'telephone':id})
    if user:    
        student_data=build_student_data(user.id,user.username,user.classname,user.telephone,user.sex)
        return response_success(student_data)
    else:
        return response_error(502,"账号获取异常")

    #用户注册
@app.route('/api/register', methods=['POST']) 
def register():  
    return None

    #用户登陆
@app.route('/api/login/<status>', methods=['POST','GET']) 
def login(status):  
    username=get_request(request,'username')
    password=get_request(request,'password')
    if status == '1': #学生登陆 
        user = mysql('SELECT * FROM student where id = :username ', {'username':username})
        if not user:
            user = mysql('SELECT * FROM student where telephone = :username ', {'username':username})
       
        if user and user.password == password:
            return response_success(f'欢迎学生{user.username}登陆')
        elif user:
            return response_error(502,'密码错误')
    else:         #教师登陆  
        user = mysql('SELECT * FROM teacher where id = :username',{'username':username})
        
        if not user:
            user = mysql('SELECT * FROM teacher where telephone = :username ', {'username':username})
        
        if user and user.password == password:
            return response_success(f'欢迎教师{user.username}登陆')
        elif user:
            return response_error(502,'密码错误')
       
    return response_error(502,'用户不存在，请切换角色或联系管理员')

    #http群聊
        #添加历史记录
@app.route('/api/add_history', methods=['GET','POST'])
def add_histroty():
    id=get_request(request,'user_id')
    group_id = get_request(request,'group_id')
    info = get_request(request,'info')
    
    if groupList.query.filter_by(id = group_id,group_userid=id).first is None or\
    groupList.query.filter_by(groupid = group_id,group_userid=id).first is None:
        return response_error(504,'该群聊不存在或未加入')
    
    new_history = groupHistory(
    userid=id,
    groupid=group_id,
    info=info,
    time = datetime.now())

    db.session.add(new_history)
    db.session.commit()
    return response_success('ok')

    #创建群聊
@app.route('/api/create_group', methods=['GET','POST'])
def create_group():
    user_id=get_request(request,'user_id')
    group_name = get_request(request,'group_name')
    groups = groupList(groupid=-1,
                   groupname=group_name,
                   group_userid=user_id)
    db.session.add(groups)
    db.session.commit()
    return response_success('ok')

    #加入群聊
@app.route('/api/add_group', methods=['GET','POST'])
def add_group():
    user_id=get_request(request,'user_id')
    group_id = get_request(request,'group_id')
    
    group_data=groupList.query.get(group_id)
    
    if group_data is None:
        return response_error(504,'群聊不存在')
    
    if groupList.query.filter_by(group_userid=user_id).first():
        return response_error(504,'群聊已经加入')
    
    groups = groupList(groupid=group_id,
                   groupname=group_data.groupname,
                   group_userid=user_id)
    db.session.add(groups)
    db.session.commit()
    return response_success('ok')
    #获取群聊
@app.route('/api/get_group', methods=['GET','POST'])
def get_group():
    user_id = get_request(request,'user_id')
    group_datas = groupList.query.filter_by(group_userid=user_id)
    
   
               
    group_list=[]
    for group_data in group_datas:
        
        groupid=group_data.groupid
        if groupid ==-1:
            groupid=group_data.id
        
        last_history=get_last_history(groupid)
            
        group_list.append({'group_id':groupid,
                           'group_name':group_data.groupname,
                          'last_history':last_history,
                          'history':get_history(groupid)})
    
    return response_success(group_list)


#Debug专区

    #显示所有的学生信息
@app.route('/debug/get_all_student', methods=['GET','POST'])
def get_all_student():
    users = Student.query.all() 
    data = [{
    'id': user.id,
    'username': user.username,
    'classname': user.classname,
    'telephone': user.telephone
    } for user in users]

    return response_success(data)
@app.route('/api/add_checkin', methods=['GET','POST'])
def add_checkin():
    user_id=get_request(request,'user_id')
    course_id=get_request(request,'course_id')  
    status=get_request(request,'status')
    
    if Student.query.get(user_id) is None:
        response_error(504,'该学生不存在')
    
    if len(teachCourse.query.filter_by(class_id=course_id).all()) ==0:#这里是因为学生不加入就不能签到，所以拿classid判断
        response_error(504,'该课程不存在')
        
    if len(teachCourse.query.filter_by(class_id=course_id,id=user_id).all()) :
        response_error(504,'该学生未加入当前课程')
             
    check = checkIn(courseid=course_id,
                    userid=user_id,
                    status=int(status),
                    reason=-1,
                    time=datetime.now())
    
    if status == '0':
        reason=get_request(request,'reason')
        if int(reason)<0 or int(reason) >3:
            response_error(504,'只能输入0~3的缺勤状况') 
        check.reason=int(reason)
    
    db.session.add(check)
    db.session.commit()        
    
    return response_success('ok')


@app.route('/api/get_checkin', methods=['GET','POST'])
def get_checkin():
    course_id=get_request(request,'course_id')
    
    checkin_list=[]
    checkin_data={}
    check_list=[]
    
    
    checkin_datas=checkIn.query.filter_by(courseid=course_id).order_by(checkIn.userid).all()
    student_name=''
    student_id=''
    
    status=['be_late','absence','sick_leave','personal_leave']#迟到，缺勤，病假，事假
    times=[[],[],[],[],[]]
    for data in checkin_datas:
        if data.userid !=student_id:
            if len(checkin_data) >0:#字典不为空(排除掉第一次的空字典)
                
                check_list.append(checkin_data.get('attendance', 0))
                for s in status:
                    check_list.append(checkin_data.get(s, 0))
                checkin_list.append({'student_name':student_name,'student_id':student_id,'checkin_list':check_list.copy(),'times':times.copy()})
                check_list.clear()
                checkin_data.clear()
                times=[[],[],[],[],[]]
            student_id=data.userid
            student_name=username[student_id] 
                
       
        if data.status == True:
            checkin_data['attendance'] = checkin_data.get('attendance', 0) + 1  
            times[0].append(data.time.strftime("%Y-%m-%d %H:%M:%S"))
        else:
            checkin_data[status[data.reason]] = checkin_data.get(status[data.reason], 0) + 1
            times[data.reason+1].append(data.time.strftime("%Y-%m-%d %H:%M:%S"))
            
    check_list.append(checkin_data.get('attendance', 0))
    for s in status:
        check_list.append(checkin_data.get(s, 0))
    checkin_list.append({'student_name':student_name,'student_id':student_id,'checkin_list':check_list.copy(),'times':times.copy()})         
    
    return response_success(checkin_list)

if __name__ == "__main__":
    socketio.run(app, debug=True, host='0.0.0.0', port=8080)